﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Collections;

namespace MvcApplication1.Models
{
    public class Searcher
    {
        private DataToSearch dts;
        public Searcher(DataToSearch dts)
        {
            this.dts = dts;
        }

        //foreach各品牌商品名称表
        //  生成该品牌搜索结果表
        //  将搜索结果表传入itemNameSearch方法，输出时该表新增hitcount列
        //  将搜索结果表传入itemKeywordSearch方法，输出时该表新增keywordhitcount列
        //  将搜索结果添加入allBrandSearchtables
        //  返回表的列顺序:ID, itemname, itemSN, addtime, image, linkaddr, price, intro, hitcount, keywordhitcount
        public DataView search(List<string> keywords)
        {
            List<DataTable> allBrandSearchtables = new List<DataTable>();
            DataTable allBrandSearchResult = null;  //各品牌排序结果合并的表
            DataSet itemNameds = this.dts.GetItemName();
            DataSet keywordds = this.dts.GetItemKeyword();
            Dictionary<string,int> brandSearchIndex = new Dictionary<string,int>();
            Dictionary<string,DataRow[]> brandSearchItem=new Dictionary<string,DataRow[]>();
            ArrayList brandname=new ArrayList();
            int searchitemcount=0;
            foreach (DataTable itemtable in itemNameds.Tables)
            {
                if (itemtable.Rows.Count == 0) continue;
                DataTable oneBrandSearchTable = itemtable.Copy();
                itemNameSearch(oneBrandSearchTable, keywords);
                itemKeywordSearch(oneBrandSearchTable, keywords, keywordds.Tables[itemtable.TableName]);
                allBrandSearchtables.Add(oneBrandSearchTable);
            }
            if(allBrandSearchtables.Count!=0) 
                allBrandSearchResult=allBrandSearchtables[0].Clone();
            int numkeyword = keywords.Count;
            foreach (DataTable dt in allBrandSearchtables)
            {
                //dt.DefaultView.Sort = "hitcount DESC,keywordhitcount DESC,addtime DESC";
                //dt.DefaultView.RowFilter = "hitcount <> 0 or keywordhitcount <> 0";
                if (numkeyword < 3)
                {
                    brandSearchItem.Add(dt.TableName + "fullmatch", dt.Select("hitcount =10" + "or keywordhitcount >=10", "hitcount DESC,keywordhitcount DESC,addtime DESC"));
                    brandSearchItem.Add(dt.TableName + "partialmatch", dt.Select("hitcount<10" + "and keywordhitcount < 10" + "and (hitcount <> 0 or keywordhitcount <> 0)", "hitcount DESC,keywordhitcount DESC,addtime DESC"));
                }
                else
                {
                    int threshold = (numkeyword - 1) * 10;
                    brandSearchItem.Add(dt.TableName + "fullmatch", dt.Select("hitcount ="+ threshold.ToString() + "or keywordhitcount >="+threshold.ToString(), "hitcount DESC,keywordhitcount DESC,addtime DESC"));
                    brandSearchItem.Add(dt.TableName + "partialmatch", dt.Select("hitcount<" + threshold.ToString() + "and keywordhitcount <" + threshold.ToString() + "and (hitcount <> 0 or keywordhitcount <> 0)", "hitcount DESC,keywordhitcount DESC,addtime DESC"));
                }
                brandSearchIndex.Add(dt.TableName+"fullmatch", 0);
                brandSearchIndex.Add(dt.TableName + "partialmatch", 0);
                brandname.Add(dt.TableName);
                searchitemcount = searchitemcount + ((DataRow[])brandSearchItem[dt.TableName+"fullmatch"]).Length+((DataRow[])brandSearchItem[dt.TableName+"partialmatch"]).Length;
            }
            bool fullhit=true;
            for (int i = 0; i < searchitemcount;)
            {
                foreach (string bn in brandname)
                {
                    if (fullhit == true)
                    {
                        if ((int)brandSearchIndex[bn + "fullmatch"] < ((DataRow[])brandSearchItem[bn + "fullmatch"]).Length)
                        {
                            DataRow row = ((DataRow[])brandSearchItem[bn + "fullmatch"])[(int)brandSearchIndex[bn + "fullmatch"]];
                            allBrandSearchResult.Rows.Add(row.ItemArray);
                            brandSearchIndex[bn + "fullmatch"] = (int)brandSearchIndex[bn + "fullmatch"]+1;
                            i++;
                        }
                    }
                    else
                    {
                        if ((int)brandSearchIndex[bn + "partialmatch"] < ((DataRow[])brandSearchItem[bn + "partialmatch"]).Length)
                        {
                            DataRow row = ((DataRow[])brandSearchItem[bn + "partialmatch"])[(int)brandSearchIndex[bn + "partialmatch"]];
                            allBrandSearchResult.Rows.Add(row.ItemArray);
                            brandSearchIndex[bn + "partialmatch"] = (int)brandSearchIndex[bn + "partialmatch"]+1;
                            i++;
                        }
                    }
                }
                fullhit = !fullhit;
            }
            return allBrandSearchResult.DefaultView;
            //foreach (DataTable dt in allBrandSearchtables)
            //{
            //    allBrandSearchResult.Merge(dt);
            //    dt.Clear();
            //}
            //allBrandSearchResult.DefaultView.Sort = "hitcount DESC,keywordhitcount DESC,itemSN,addtime DESC";
            //allBrandSearchResult.DefaultView.RowFilter = "hitcount <> 0 or keywordhitcount <> 0";
            //return allBrandSearchResult.DefaultView;     
            //返回表的列顺序:ID, itemname, itemSN, addtime, image, linkaddr, price, intro, hitcount, keywordhitcount
        }
        //一个品牌的商品名称表搜索，结果为oneBrandSearchTable表中增加的hitcount列
        //算法
        //Foreach 品牌的datatable
        //    克隆当前品牌datatable并添加hitcount列和groupid列
        //    Foreach keyword
        //        为全部匹配生成一个dataview
        //        dataview每一项的hitcount加10
        //        为部分匹配生成一个dataview
        //        dataview每一项的hitcount加1
        private void itemNameSearch(DataTable oneBrandSearchTable, List<string> keywords)
        {
            DataColumn hitcount = new DataColumn("hitcount", System.Type.GetType("System.Int16"));   //添加命中次数列
            hitcount.DefaultValue = 0;
            oneBrandSearchTable.Columns.Add(hitcount);
            foreach (string keyword in keywords)
            {
                DataView allmatch = new DataView(oneBrandSearchTable, "itemname='" + keyword + "'", "", DataViewRowState.CurrentRows);
                DataView partialmatch = new DataView(oneBrandSearchTable, "(not itemname='" + keyword + "') and itemname like '%" + keyword + "%'", "", DataViewRowState.CurrentRows);
                for (int i = 0; i < allmatch.Count; i++)
                {
                    allmatch[i]["hitcount"] = Convert.ToInt16(allmatch[i]["hitcount"]) + 10;//确保全部匹配的商品排在部分匹配商品的前面
                }
                for (int i = 0; i < partialmatch.Count; i++)
                {
                    partialmatch[i]["hitcount"] = Convert.ToInt16(partialmatch[i]["hitcount"]) + 1;
                }
            }
        }

        //一个品牌的商品关键字搜索，结果为oneBrandSearchTable表中增加的keywordhitcount列
        //算法
        //  foreach keyword
        //      为全部匹配生成一个dataview
        //      dataview中每一项在onebrandSearchTable的对应项的keywordhitcount加10
        //      为部分匹配生成一个dataview
        //      dataview中每一项在onebrandSearchTable的对应项的keywordhitcount加1
        private void itemKeywordSearch(DataTable oneBrandSearchTable, List<string> keywords, DataTable brandKeywords)
        {
            DataColumn hitcount = new DataColumn("keywordhitcount", System.Type.GetType("System.Int16"));   //添加命中次数列
            hitcount.DefaultValue = 0;
            oneBrandSearchTable.Columns.Add(hitcount);
            oneBrandSearchTable.DefaultView.Sort = "ID";
            foreach (string keyword in keywords)
            {
                DataView allmatch = new DataView(brandKeywords, "keyword='" + keyword + "'", "", DataViewRowState.CurrentRows);
                DataView partialmatch = new DataView(brandKeywords, "(not keyword='" + keyword + "') and keyword like '%" + keyword + "%'", "", DataViewRowState.CurrentRows);
                for (int i = 0; i < allmatch.Count; i++)
                {
                    oneBrandSearchTable.Rows[oneBrandSearchTable.DefaultView.Find(allmatch[i]["ID"])]["keywordhitcount"] = Convert.ToInt16(oneBrandSearchTable.Rows[oneBrandSearchTable.DefaultView.Find(allmatch[i]["ID"])]["keywordhitcount"]) + 10;
                }
                for (int i = 0; i < partialmatch.Count; i++)
                {
                    //oneBrandSearchTable.Rows[oneBrandSearchTable.DefaultView.Find(allmatch[i]["ID"])]["keywordhitcount"] = Convert.ToInt16(oneBrandSearchTable.Rows[oneBrandSearchTable.DefaultView.Find(allmatch[i]["ID"])]["keywordhitcount"]) + 1;
                    oneBrandSearchTable.Rows[oneBrandSearchTable.DefaultView.Find(partialmatch[i]["ID"])]["keywordhitcount"] = Convert.ToInt16(oneBrandSearchTable.Rows[oneBrandSearchTable.DefaultView.Find(partialmatch[i]["ID"])]["keywordhitcount"]) + 1;
                }

            }
        }

    }
}